package encoder

import (
	"crypto/rand"
	aacRTP "gitee.com/general252/gomedia/go-rtsp/rtp"
	"github.com/pion/rtp"

	"github.com/bluenviron/gortsplib/v4/pkg/rtptime"
	"time"
)

const (
	rtpVersion            = 2
	defaultPayloadMaxSize = 1460 // 1500 (UDP MTU) - 20 (IP header) - 8 (UDP header) - 12 (RTP header)
)

func randUint32() (uint32, error) {
	var b [4]byte
	_, err := rand.Read(b[:])
	if err != nil {
		return 0, err
	}
	return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]), nil
}

type AACEncoder1 struct {
	// payload type of packets.
	PayloadType uint8

	// SSRC of packets (optional).
	// It defaults to a random value.
	SSRC *uint32

	// initial sequence number of packets (optional).
	// It defaults to a random value.
	InitialSequenceNumber *uint16

	// initial timestamp of packets (optional).
	// It defaults to a random value.
	InitialTimestamp *uint32

	// maximum size of packet payloads (optional).
	// It defaults to 1460.
	PayloadMaxSize int

	// sample rate of packets.
	SampleRate int

	// The number of bits in which the AU-size field is encoded in the AU-header.
	SizeLength int

	// The number of bits in which the AU-Index is encoded in the first AU-header.
	IndexLength int

	// The number of bits in which the AU-Index-delta field is encoded in any non-first AU-header.
	IndexDeltaLength int

	sequenceNumber uint16
	timeEncoder    *rtptime.Encoder
	encoder        *aacRTP.AACPacker
}

// Init initializes the encoder.
func (e *AACEncoder1) Init() error {

	if e.SSRC == nil {
		v, err := randUint32()
		if err != nil {
			return err
		}
		e.SSRC = &v
	}
	if e.InitialSequenceNumber == nil {
		v, err := randUint32()
		if err != nil {
			return err
		}
		v2 := uint16(v)
		e.InitialSequenceNumber = &v2
	}
	if e.InitialTimestamp == nil {
		v, err := randUint32()
		if err != nil {
			return err
		}
		e.InitialTimestamp = &v
	}
	if e.PayloadMaxSize == 0 {
		e.PayloadMaxSize = defaultPayloadMaxSize
	}

	e.sequenceNumber = *e.InitialSequenceNumber
	e.timeEncoder = rtptime.NewEncoder(e.SampleRate, *e.InitialTimestamp)

	e.encoder = aacRTP.NewAACPacker(e.PayloadType, *e.SSRC, e.sequenceNumber, e.PayloadMaxSize)
	return nil
}

func (e *AACEncoder1) Encode(aus [][]byte, pts time.Duration) ([]*rtp.Packet, error) {
	var out []*rtp.Packet
	for _, au := range aus {
		pkts, err := e.Encode2(au, pts)
		if err != nil {
			return nil, err
		}

		out = append(out, pkts...)
	}

	return out, nil
}

func (e *AACEncoder1) Encode2(nalu []byte, pts time.Duration) ([]*rtp.Packet, error) {
	var out []*rtp.Packet
	e.encoder.HookRtp(func(pkg *aacRTP.RtpPacket) {
		var packet rtp.Packet
		if err := packet.Unmarshal(pkg.Encode()); err == nil {
			out = append(out, &packet)
		}
	})

	timestamp := e.timeEncoder.Encode(pts)
	if err := e.encoder.Pack(nalu, timestamp); err != nil {
		return nil, err
	}

	return out, nil
}
